package sensorBoard.io;

import java.util.Vector;

import javax.microedition.rms.InvalidRecordIDException;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
import javax.microedition.rms.RecordStoreFullException;
import javax.microedition.rms.RecordStoreNotFoundException;
import javax.microedition.rms.RecordStoreNotOpenException;

import sensorBoard.ISensorBoardComponent;
import server.interfaces.ISensorBoardManager;

import com.CharNotValidException;
import com.Event;
import com.LedsManager;
import com.ParamNotFoundException;
import com.ParamsLabel;
import com.sun.spot.resources.transducers.LEDColor;
import com.sun.squawk.util.StringTokenizer;

/**
 * FlashManager manages the access to the node Flash Memory. It's possible to store byte arrays in a RecordManagementStore
 * @author Francesco Aiello, Antonio Guerrieri, Raffaele Gravina
 *
 */
public class FlashManager implements ISensorBoardComponent {
	
	private byte [] handlableEvents = {Event.FLS_ADD, 
			Event.FLS_DELETE, 
			Event.FLS_SET,
			Event.FLS_GET};
	
	private ISensorBoardManager sensorBoardManager;
	private Vector recordStoreVector;
	/**
	 * The constructor needs to know own ioManager, the access to LED resource is realized thanks to LEDManager utility class 
	 * @param sensorBoardManager its own manager
	 */
	public FlashManager (ISensorBoardManager sensorBoardManager) {
		this.sensorBoardManager = sensorBoardManager;
	}
	
	public boolean IsEventHandlable(byte eventName) {
		for (int i = 0; i < handlableEvents.length; i++) 
			if (this.handlableEvents[i] == eventName)
				return true;
		return false;
	}
	
	public void handleEvent(Event event) {
		
		
		try {
			byte eventName = event.getName();
			switch (eventName) {
				case Event.FLS_ADD:
				
					try {
						RecordStore rms = this.getRMS(event.getSourceID());
						if (rms == null)
							rms = RecordStore.openRecordStore(event.getSourceID(), true);
						if (this.recordStoreVector == null)
							this.recordStoreVector = new Vector();
						recordStoreVector.addElement(rms);
						StringTokenizer st = new StringTokenizer(event.getParam(ParamsLabel.FLS_DATA), "|");							
						int length = Integer.parseInt(st.nextToken());
						byte byte_data[] = new byte[length];
						for (int i = 0; i < length; i++)						
							byte_data[i] = Byte.parseByte(st.nextToken());								
						
						int recordID = rms.addRecord(byte_data, 0, length);
						Event backEvent = new Event(event.getSourceID(), event.getSourceID(), Event.FLS_ADD, Event.NOW);
						backEvent.setParam(ParamsLabel.FLS_RECORD_ID, "" + recordID);
						this.send(backEvent);
						
					} 
					catch (RecordStoreFullException e) {
						e.printStackTrace();
					}
					catch (RecordStoreNotFoundException e) {						
						e.printStackTrace();
					}
					catch (RecordStoreException e) {
						e.printStackTrace();
					}
					catch (CharNotValidException e) {
						e.printStackTrace();
					}
					
				break;
				case Event.FLS_DELETE:
					try {
						RecordStore rsDelete = this.getRMS(event.getSourceID());
						rsDelete.deleteRecord(Integer.parseInt(event.getParam(ParamsLabel.FLS_RECORD_ID)));
						if (rsDelete.getNumRecords() == 0)
						{
							this.recordStoreVector.removeElement(rsDelete);
							rsDelete.closeRecordStore();
						}
					}
					catch (RecordStoreNotOpenException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					catch (InvalidRecordIDException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					catch (RecordStoreException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}					
					
				break;
				case Event.FLS_GET:
					try {
						RecordStore rsGet = this.getRMS(event.getSourceID());
						byte [] record = rsGet.getRecord(Integer.parseInt(event.getParam(ParamsLabel.FLS_RECORD_ID)));
						String string_dati = record.length + "|";
						
						for (int i = 0; i < record.length; i++) {
							string_dati += record[i] + "|";
						}
											
						Event flsGet = new Event(rsGet.getName(), rsGet.getName(), Event.FLS_GET, Event.NOW);
						flsGet.setParam(ParamsLabel.FLS_DATA, string_dati);
						this.send(flsGet);
					}
					catch (RecordStoreNotOpenException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					catch (InvalidRecordIDException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					catch (RecordStoreException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					catch (CharNotValidException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				break;
				case Event.FLS_SET:
					try {
						RecordStore rsSet = this.getRMS(event.getSourceID());
						
						StringTokenizer st = new StringTokenizer(event.getParam(ParamsLabel.FLS_DATA), "|");							
						int length = Integer.parseInt(st.nextToken());
						byte byte_data[] = new byte[length];
						for (int i = 0; i < length; i++)						
							byte_data[i] = Byte.parseByte(st.nextToken());								
						
						rsSet.setRecord(Integer.parseInt(event.getParam(ParamsLabel.FLS_RECORD_ID)), 
								byte_data, 0, byte_data.length);
					}
					catch (RecordStoreNotOpenException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					catch (InvalidRecordIDException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					catch (RecordStoreFullException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					catch (RecordStoreException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
										
				break;
			}
		}
		catch (NumberFormatException e) {
			LedsManager.error(LEDColor.YELLOW);
			e.printStackTrace();
		}
		catch (ParamNotFoundException e) {
			LedsManager.error(LEDColor.YELLOW);
			e.printStackTrace();
		}
		
	}
	
	public void send(Event backEvent) {
		this.sensorBoardManager.send(backEvent);
	}
	
	public boolean terminateListener(String sensorBoardComponentID) {
		return false;
	}
	
	/**
	 * Converts a string in a LEDColor object.
	 * The possible strings are: BLUE, CHARTREUSE, CYAN, GREEN, MAGENTA, MAUVE, ORANGE, PUCE, TURQUOISE, WHITE, YELLOW
	 * If the string doesn't exist the function returns null.
	 * @param color the string that specifies the color
	 * @return LEDColor object if the color is found, "null" otherwise
	 */
	public RecordStore getRMS (String agentID) {
		
		RecordStore rsTemp;
		for (int i = 0; i < recordStoreVector.size(); i++) {
			rsTemp = (RecordStore)recordStoreVector.elementAt(i);
			try {
				if (rsTemp.getName().equals(agentID))
					return rsTemp;
			}
			catch (RecordStoreNotOpenException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return null;
	}

	
}


